//////////////////////////////////////////////////////////////////////
//                                                                  //
//    pfpu_marocchino_muldiv                                        //
//                                                                  //
//    This file is part of the MAROCCHINO project                   //
//    https://github.com/openrisc/or1k_marocchino                   //
//                                                                  //
//    Description                                                   //
//    combined multiplier/divisor pipeline for                      //
//    single and double precision floating point numbers            //
//    for MAROCCHINO pipeline                                       //
//                                                                  //
//    Author(s):                                                    //
//          Andrey Bacherov, avbacherov@opencores.org               //
//                                                                  //
//////////////////////////////////////////////////////////////////////
//                                                                  //
//  Copyright (C) 2015 - 2019                                       //
//                                                                  //
//  This source file may be used and distributed without            //
//  restriction provided that this copyright statement is not       //
//  removed from the file and that any derivative work contains     //
//  the original copyright notice and the associated disclaimer.    //
//                                                                  //
//    THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY           //
//  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED       //
//  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS       //
//  FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR          //
//  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,             //
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES        //
//  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE       //
//  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR            //
//  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      //
//  LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT      //
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT      //
//  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE             //
//  POSSIBILITY OF SUCH DAMAGE.                                     //
//////////////////////////////////////////////////////////////////////

`include "or1k_defines.v"

module pfpu_marocchino_muldiv
(
  // clocks and resets
  input             cpu_clk,
  // pipe controls
  input             pipeline_flush_i,   // flush pipe
  input             mul_start_i,
  input             div_start_i,
  output            muldiv_taking_op_o,
  output            mul_rdy_o,          // multiplier ready
  input             rnd_taking_mul_i,
  output            div_rdy_o,          // divider ready
  input             rnd_taking_div_i,
  // input 'a' related values
  input             signa_i,
  input      [12:0] exp13a_i,
  input      [52:0] fract53a_i,
  // input 'b' related values
  input             signb_i,
  input      [12:0] exp13b_i,
  input      [52:0] fract53b_i,
  // 'a'/'b' related
  input             exec_op_fp64_arith_i,
  input             dbz_i,           // division by zero detection
  input             opc_0_i,         // force intermediate results to zero
  // MUL outputs
  output            mul_sign_o,      // signum
  output     [10:0] mul_shr_o,       // do right shift in align stage
  output     [12:0] mul_exp13sh0_o,  // exponent for no shift in align
  output     [56:0] mul_fract57_o,   // fractional with appended {r,s} bits
  // DIV outputs
  output            div_sign_o,      // signum
  output     [10:0] div_shr_o,       // do right shift in align stage
  output            div_shl_o,       // do left shift in align stage
  output     [12:0] div_exp13sh0_o,  // exponent for no shift in align
  output     [56:0] div_fract57_o,   // fractional with appended {r,s} bits
  output            div_dbz_o        // div division by zero flag
);

  /*
     Any stage's output is registered.
     Definitions:
       s??o_name - "S"tage number "??", "O"utput
       s??t_name - "S"tage number "??", "T"emporary (internally)
  */


  // MUL/DIV pipe controls
  //  ## ready flags
  reg  sIo_ready, sIo_pending;
  reg  s0o_mul_ready, s0o_div_ready;
  reg  s1o_mul_ready, s1o_div_ready;
  //  ## Multiplier / Divider is taking operands
  wire mul_taking_op, mul_busy;
  wire div_taking_op, div_busy;
  //  ## per stage busy flags
  wire s1_busy = mul_busy | div_busy;
  wire s0_busy = (s0o_mul_ready | s0o_div_ready) & s1_busy;
  wire sI_busy = sIo_ready & sIo_pending;
  //  ## per stage advance flags
  wire sI_adv = (mul_start_i   | div_start_i)   & ~sI_busy;
  wire s0_adv = (sIo_ready     | sIo_pending)   & ~s0_busy;
  wire s1_adv = (s0o_mul_ready | s0o_div_ready) & ~s1_busy;
  wire s2_adv =  mul_taking_op | div_taking_op;
  //  ## MUL/DIV taking operands
  assign muldiv_taking_op_o = sI_adv;


  /**** Stage I: [I]nput latches ****/


  // reg 'a' related values
  reg  [12:0] sIo_exp13a;
  reg  [52:0] sIo_fract53a;
  // reg 'b' related values
  reg  [12:0] sIo_exp13b;
  reg  [52:0] sIo_fract53b;
  // 'a'/'b' related
  reg         sIo_signc;
  reg         sIo_op_fp64_arith;
  reg         sIo_op_mul;
  reg         sIo_op_div;
  reg         sIo_dbz;
  reg         sIo_opc_0;

  // ---
  always @(posedge cpu_clk) begin
    if (sI_adv) begin
      // reg 'a' related values
      sIo_exp13a    <= exp13a_i;
      sIo_fract53a  <= fract53a_i;
      // reg 'b' related values
      sIo_exp13b    <= exp13b_i;
      sIo_fract53b  <= fract53b_i;
      // 'a'/'b' related
      sIo_signc   <= signa_i ^ signb_i;
      sIo_op_fp64_arith <= exec_op_fp64_arith_i;
      sIo_op_mul  <= mul_start_i;
      sIo_op_div  <= div_start_i;
      sIo_dbz     <= dbz_i;
      sIo_opc_0   <= opc_0_i;
    end
  end

  // "stage I is ready" flag
  always @(posedge cpu_clk) begin
    if (pipeline_flush_i)
      sIo_ready <= 1'b0;
    else if (sI_adv)
      sIo_ready <= 1'b1;
    else if (s0_adv)
      sIo_ready <= sI_busy;
    else if (~sIo_pending)
      sIo_ready <= 1'b0;
  end // @cpu-clock

  // "there are pending data " flag
  always @(posedge cpu_clk) begin
    if (pipeline_flush_i)
      sIo_pending <= 1'b0;
    else if (s0_adv)
      sIo_pending <= 1'b0;
    else if (~sIo_pending)
      sIo_pending <= sIo_ready;
  end // @cpu-clock


  /**** Stage #0: NLZ computation ****/


  // count leading zeros
  reg [5:0] s0t_nlza;
  always @(sIo_fract53a) begin
    (* parallel_case *)
    casez (sIo_fract53a)
      53'b1????????????????????????????????????????????????????: s0t_nlza =  6'd0;
      53'b01???????????????????????????????????????????????????: s0t_nlza =  6'd1;
      53'b001??????????????????????????????????????????????????: s0t_nlza =  6'd2;
      53'b0001?????????????????????????????????????????????????: s0t_nlza =  6'd3;
      53'b00001????????????????????????????????????????????????: s0t_nlza =  6'd4;
      53'b000001???????????????????????????????????????????????: s0t_nlza =  6'd5;
      53'b0000001??????????????????????????????????????????????: s0t_nlza =  6'd6;
      53'b00000001?????????????????????????????????????????????: s0t_nlza =  6'd7;
      53'b000000001????????????????????????????????????????????: s0t_nlza =  6'd8;
      53'b0000000001???????????????????????????????????????????: s0t_nlza =  6'd9;
      53'b00000000001??????????????????????????????????????????: s0t_nlza = 6'd10;
      53'b000000000001?????????????????????????????????????????: s0t_nlza = 6'd11;
      53'b0000000000001????????????????????????????????????????: s0t_nlza = 6'd12;
      53'b00000000000001???????????????????????????????????????: s0t_nlza = 6'd13;
      53'b000000000000001??????????????????????????????????????: s0t_nlza = 6'd14;
      53'b0000000000000001?????????????????????????????????????: s0t_nlza = 6'd15;
      53'b00000000000000001????????????????????????????????????: s0t_nlza = 6'd16;
      53'b000000000000000001???????????????????????????????????: s0t_nlza = 6'd17;
      53'b0000000000000000001??????????????????????????????????: s0t_nlza = 6'd18;
      53'b00000000000000000001?????????????????????????????????: s0t_nlza = 6'd19;
      53'b000000000000000000001????????????????????????????????: s0t_nlza = 6'd20;
      53'b0000000000000000000001???????????????????????????????: s0t_nlza = 6'd21;
      53'b00000000000000000000001??????????????????????????????: s0t_nlza = 6'd22;
      53'b000000000000000000000001?????????????????????????????: s0t_nlza = 6'd23;
      53'b0000000000000000000000001????????????????????????????: s0t_nlza = 6'd24;
      53'b00000000000000000000000001???????????????????????????: s0t_nlza = 6'd25;
      53'b000000000000000000000000001??????????????????????????: s0t_nlza = 6'd26;
      53'b0000000000000000000000000001?????????????????????????: s0t_nlza = 6'd27;
      53'b00000000000000000000000000001????????????????????????: s0t_nlza = 6'd28;
      53'b000000000000000000000000000001???????????????????????: s0t_nlza = 6'd29;
      53'b0000000000000000000000000000001??????????????????????: s0t_nlza = 6'd30;
      53'b00000000000000000000000000000001?????????????????????: s0t_nlza = 6'd31;
      53'b000000000000000000000000000000001????????????????????: s0t_nlza = 6'd32;
      53'b0000000000000000000000000000000001???????????????????: s0t_nlza = 6'd33;
      53'b00000000000000000000000000000000001??????????????????: s0t_nlza = 6'd34;
      53'b000000000000000000000000000000000001?????????????????: s0t_nlza = 6'd35;
      53'b0000000000000000000000000000000000001????????????????: s0t_nlza = 6'd36;
      53'b00000000000000000000000000000000000001???????????????: s0t_nlza = 6'd37;
      53'b000000000000000000000000000000000000001??????????????: s0t_nlza = 6'd38;
      53'b0000000000000000000000000000000000000001?????????????: s0t_nlza = 6'd39;
      53'b00000000000000000000000000000000000000001????????????: s0t_nlza = 6'd40;
      53'b000000000000000000000000000000000000000001???????????: s0t_nlza = 6'd41;
      53'b0000000000000000000000000000000000000000001??????????: s0t_nlza = 6'd42;
      53'b00000000000000000000000000000000000000000001?????????: s0t_nlza = 6'd43;
      53'b000000000000000000000000000000000000000000001????????: s0t_nlza = 6'd44;
      53'b0000000000000000000000000000000000000000000001???????: s0t_nlza = 6'd45;
      53'b00000000000000000000000000000000000000000000001??????: s0t_nlza = 6'd46;
      53'b000000000000000000000000000000000000000000000001?????: s0t_nlza = 6'd47;
      53'b0000000000000000000000000000000000000000000000001????: s0t_nlza = 6'd48;
      53'b00000000000000000000000000000000000000000000000001???: s0t_nlza = 6'd49;
      53'b000000000000000000000000000000000000000000000000001??: s0t_nlza = 6'd50;
      53'b0000000000000000000000000000000000000000000000000001?: s0t_nlza = 6'd51;
      53'b00000000000000000000000000000000000000000000000000001: s0t_nlza = 6'd52;
      53'b00000000000000000000000000000000000000000000000000000: s0t_nlza =  6'd0; // zero rezult
    endcase
  end // nlz for 'a'

  // count leading zeros
  reg [5:0] s0t_nlzb;
  always @(sIo_fract53b) begin
    (* parallel_case *)
    casez (sIo_fract53b)
      53'b1????????????????????????????????????????????????????: s0t_nlzb =  6'd0;
      53'b01???????????????????????????????????????????????????: s0t_nlzb =  6'd1;
      53'b001??????????????????????????????????????????????????: s0t_nlzb =  6'd2;
      53'b0001?????????????????????????????????????????????????: s0t_nlzb =  6'd3;
      53'b00001????????????????????????????????????????????????: s0t_nlzb =  6'd4;
      53'b000001???????????????????????????????????????????????: s0t_nlzb =  6'd5;
      53'b0000001??????????????????????????????????????????????: s0t_nlzb =  6'd6;
      53'b00000001?????????????????????????????????????????????: s0t_nlzb =  6'd7;
      53'b000000001????????????????????????????????????????????: s0t_nlzb =  6'd8;
      53'b0000000001???????????????????????????????????????????: s0t_nlzb =  6'd9;
      53'b00000000001??????????????????????????????????????????: s0t_nlzb = 6'd10;
      53'b000000000001?????????????????????????????????????????: s0t_nlzb = 6'd11;
      53'b0000000000001????????????????????????????????????????: s0t_nlzb = 6'd12;
      53'b00000000000001???????????????????????????????????????: s0t_nlzb = 6'd13;
      53'b000000000000001??????????????????????????????????????: s0t_nlzb = 6'd14;
      53'b0000000000000001?????????????????????????????????????: s0t_nlzb = 6'd15;
      53'b00000000000000001????????????????????????????????????: s0t_nlzb = 6'd16;
      53'b000000000000000001???????????????????????????????????: s0t_nlzb = 6'd17;
      53'b0000000000000000001??????????????????????????????????: s0t_nlzb = 6'd18;
      53'b00000000000000000001?????????????????????????????????: s0t_nlzb = 6'd19;
      53'b000000000000000000001????????????????????????????????: s0t_nlzb = 6'd20;
      53'b0000000000000000000001???????????????????????????????: s0t_nlzb = 6'd21;
      53'b00000000000000000000001??????????????????????????????: s0t_nlzb = 6'd22;
      53'b000000000000000000000001?????????????????????????????: s0t_nlzb = 6'd23;
      53'b0000000000000000000000001????????????????????????????: s0t_nlzb = 6'd24;
      53'b00000000000000000000000001???????????????????????????: s0t_nlzb = 6'd25;
      53'b000000000000000000000000001??????????????????????????: s0t_nlzb = 6'd26;
      53'b0000000000000000000000000001?????????????????????????: s0t_nlzb = 6'd27;
      53'b00000000000000000000000000001????????????????????????: s0t_nlzb = 6'd28;
      53'b000000000000000000000000000001???????????????????????: s0t_nlzb = 6'd29;
      53'b0000000000000000000000000000001??????????????????????: s0t_nlzb = 6'd30;
      53'b00000000000000000000000000000001?????????????????????: s0t_nlzb = 6'd31;
      53'b000000000000000000000000000000001????????????????????: s0t_nlzb = 6'd32;
      53'b0000000000000000000000000000000001???????????????????: s0t_nlzb = 6'd33;
      53'b00000000000000000000000000000000001??????????????????: s0t_nlzb = 6'd34;
      53'b000000000000000000000000000000000001?????????????????: s0t_nlzb = 6'd35;
      53'b0000000000000000000000000000000000001????????????????: s0t_nlzb = 6'd36;
      53'b00000000000000000000000000000000000001???????????????: s0t_nlzb = 6'd37;
      53'b000000000000000000000000000000000000001??????????????: s0t_nlzb = 6'd38;
      53'b0000000000000000000000000000000000000001?????????????: s0t_nlzb = 6'd39;
      53'b00000000000000000000000000000000000000001????????????: s0t_nlzb = 6'd40;
      53'b000000000000000000000000000000000000000001???????????: s0t_nlzb = 6'd41;
      53'b0000000000000000000000000000000000000000001??????????: s0t_nlzb = 6'd42;
      53'b00000000000000000000000000000000000000000001?????????: s0t_nlzb = 6'd43;
      53'b000000000000000000000000000000000000000000001????????: s0t_nlzb = 6'd44;
      53'b0000000000000000000000000000000000000000000001???????: s0t_nlzb = 6'd45;
      53'b00000000000000000000000000000000000000000000001??????: s0t_nlzb = 6'd46;
      53'b000000000000000000000000000000000000000000000001?????: s0t_nlzb = 6'd47;
      53'b0000000000000000000000000000000000000000000000001????: s0t_nlzb = 6'd48;
      53'b00000000000000000000000000000000000000000000000001???: s0t_nlzb = 6'd49;
      53'b000000000000000000000000000000000000000000000000001??: s0t_nlzb = 6'd50;
      53'b0000000000000000000000000000000000000000000000000001?: s0t_nlzb = 6'd51;
      53'b00000000000000000000000000000000000000000000000000001: s0t_nlzb = 6'd52;
      53'b00000000000000000000000000000000000000000000000000000: s0t_nlzb =  6'd0; // zero rezult
    endcase
  end // nlz of 'b'

  // pre-norm stage outputs and pendings
  reg        s0o_opc_0,         s0o_opc_0_p;
  reg        s0o_signc,         s0o_signc_p;
  reg [12:0] s0o_exp13a,        s0o_exp13a_p;
  reg [52:0] s0o_fract53a,      s0o_fract53a_p;
  reg  [5:0] s0o_shla,          s0o_shla_p;
  reg [12:0] s0o_exp13b,        s0o_exp13b_p;
  reg [52:0] s0o_fract53b,      s0o_fract53b_p;
  reg  [5:0] s0o_shlb,          s0o_shlb_p;
  reg        s0o_dbz,           s0o_dbz_p;
  reg        s0o_op_fp64_arith, s0o_op_fp64_arith_p;
  // MUL/DIV OP pendings
  reg s0o_op_div_p, s0o_op_mul_p;
  // pendings
  always @(posedge cpu_clk) begin
    if (~sIo_pending) begin
      s0o_opc_0_p         <= sIo_opc_0;
      s0o_signc_p         <= sIo_signc;
      s0o_exp13a_p        <= sIo_exp13a;
      s0o_fract53a_p      <= sIo_fract53a;
      s0o_shla_p          <= s0t_nlza;
      s0o_exp13b_p        <= sIo_exp13b;
      s0o_fract53b_p      <= sIo_fract53b;
      s0o_shlb_p          <= s0t_nlzb;
      s0o_dbz_p           <= sIo_dbz;
      s0o_op_fp64_arith_p <= sIo_op_fp64_arith;
      s0o_op_div_p        <= sIo_op_div;
      s0o_op_mul_p        <= sIo_op_mul;
    end // push pipe
  end
  // registering
  always @(posedge cpu_clk) begin
    if (s0_adv) begin
      s0o_opc_0         <= sIo_pending ? s0o_opc_0_p         : sIo_opc_0;
      s0o_signc         <= sIo_pending ? s0o_signc_p         : sIo_signc;
      s0o_exp13a        <= sIo_pending ? s0o_exp13a_p        : sIo_exp13a;
      s0o_fract53a      <= sIo_pending ? s0o_fract53a_p      : sIo_fract53a;
      s0o_shla          <= sIo_pending ? s0o_shla_p          : s0t_nlza;
      s0o_exp13b        <= sIo_pending ? s0o_exp13b_p        : sIo_exp13b;
      s0o_fract53b      <= sIo_pending ? s0o_fract53b_p      : sIo_fract53b;
      s0o_shlb          <= sIo_pending ? s0o_shlb_p          : s0t_nlzb;
      s0o_dbz           <= sIo_pending ? s0o_dbz_p           : sIo_dbz;
      s0o_op_fp64_arith <= sIo_pending ? s0o_op_fp64_arith_p : sIo_op_fp64_arith;
    end // push pipe
  end

  // stage #0 is ready
  always @(posedge cpu_clk) begin
    if (pipeline_flush_i) begin
      s0o_div_ready <= 1'b0;
      s0o_mul_ready <= 1'b0;
    end
    else if (s0_adv) begin
      s0o_div_ready <= sIo_pending ? s0o_op_div_p : sIo_op_div;
      s0o_mul_ready <= sIo_pending ? s0o_op_mul_p : sIo_op_mul;
    end
    else if (s1_adv) begin
      s0o_div_ready <= 1'b0;
      s0o_mul_ready <= 1'b0;
    end
  end // @clock


  /**** Stage #1: normalization stage ****/


  // left-shift the dividend and divisor
  wire [52:0] s1t_fract53a = s0o_fract53a << s0o_shla;
  wire [52:0] s1t_fract53b = s0o_fract53b << s0o_shlb;
  // re-pack bits for single precision multiplier to LSBs
  wire [52:0] s1t_fract53a_mux = (s0o_div_ready | s0o_op_fp64_arith) ? (s1t_fract53a) : ({29'd0,s1t_fract53a[52:29]});
  wire [52:0] s1t_fract53b_mux = (s0o_div_ready | s0o_op_fp64_arith) ? (s1t_fract53b) : ({29'd0,s1t_fract53b[52:29]});

  // select exponent bias
  wire [12:0] s1t_exp_bias = s0o_op_fp64_arith ? 13'd1023 : 13'd127;
  // compute new exponent
  wire [12:0] s1t_exp13mux =
    ({13{s0o_div_ready}} & (s0o_exp13a - {7'd0,s0o_shla} - s0o_exp13b + {7'd0,s0o_shlb} + s1t_exp_bias)) |
    ({13{s0o_mul_ready}} & (s0o_exp13a - {7'd0,s0o_shla} + s0o_exp13b - {7'd0,s0o_shlb} - s1t_exp_bias));

  // force result to zero
  wire [12:0] s1t_exp13c = s1t_exp13mux & {13{~s0o_opc_0}};

  // stage #1 outputs
  reg        s1o_opc_0;
  reg        s1o_signc;
  reg [12:0] s1o_exp13c;
  reg [52:0] s1o_fract53a;
  reg [52:0] s1o_fract53b;
  reg        s1o_dbz;
  reg        s1o_op_fp64_arith;
  //   registering
  always @(posedge cpu_clk) begin
    if (s1_adv) begin
      s1o_opc_0         <= s0o_opc_0;
      s1o_signc         <= s0o_signc;
      s1o_exp13c        <= s1t_exp13c;
      s1o_fract53a      <= s1t_fract53a_mux;
      s1o_fract53b      <= s1t_fract53b_mux;
      s1o_dbz           <= s0o_dbz;
      s1o_op_fp64_arith <= s0o_op_fp64_arith;
    end // advance pipe
  end // @clock

  // ready for MUL instruction
  always @(posedge cpu_clk) begin
    if (pipeline_flush_i) begin
      s1o_mul_ready <= 1'b0;
      s1o_div_ready <= 1'b0;
    end
    else if (s1_adv) begin
      s1o_mul_ready <= s0o_mul_ready;
      s1o_div_ready <= s0o_div_ready;
    end
    else if (s2_adv) begin
      s1o_mul_ready <= 1'b0;
      s1o_div_ready <= 1'b0;
    end
  end // @clock


  /**** Run Multiplier or Divider ****/


  // right shift value
  // variants (maximum possible value is 1126 -> 11 bits):
  wire [10:0] s2t_shrx =
    // negative exponent sum: (-e+1) = (~e + 2)
    //   (!) takes 1x.xx case into account automatically
    s1o_exp13c[12] ? ((~s1o_exp13c[10:0]) + 11'd2) :
    // (a) zero exponent sum (denorm. result potentially)
    //   (!) takes 1x.xx case into account automatically
    // (b) normal case
    //   (!) 1x.xx case is processed in next stage
                     {10'd0,~(|s1o_exp13c)};

  // zero exponent for forced zero result
  wire [12:0] s2t_exp13c = s1o_opc_0 ? 13'd0 : s1o_exp13c;


  /**** Multiplier instance ****/


  pfpu_marocchino_mul u_fp64_mul
  (
    // clocks and resets
    .cpu_clk              (cpu_clk), // FP64_MUL
    // pipe controls
    .pipeline_flush_i     (pipeline_flush_i), // FP64_MUL
    .s1o_mul_ready_i      (s1o_mul_ready), // FP64_MUL
    .mul_busy_o           (mul_busy), // FP64_MUL
    .mul_taking_op_o      (mul_taking_op), // FP64_MUL
    .mul_rdy_o            (mul_rdy_o), // FP64_MUL
    .rnd_taking_mul_i     (rnd_taking_mul_i), // FP64_MUL
    // operands
    .s1o_signc_i          (s1o_signc), // FP64_MUL
    .s2t_exp13c_i         (s2t_exp13c), // FP64_MUL
    .s2t_shrx_i           (s2t_shrx), // FP64_MUL
    .s1o_opc_0_i          (s1o_opc_0), // FP64_MUL
    .s1o_fract53a_i       (s1o_fract53a), // FP64_MUL
    .s1o_fract53b_i       (s1o_fract53b), // FP64_MUL
    .s1o_op_fp64_arith_i  (s1o_op_fp64_arith), // FP64_MUL
    // MUL outputs
    .mul_sign_o           (mul_sign_o), // FP64_MUL
    .mul_shr_o            (mul_shr_o), // FP64_MUL
    .mul_exp13sh0_o       (mul_exp13sh0_o), // FP64_MUL
    .mul_fract57_o        (mul_fract57_o) // FP64_MUL
  );


  /**** Divider instance ****/


  pfpu_marocchino_div u_fp64_div
  (
    // clocks and resets
    .cpu_clk              (cpu_clk), // FP64_DIV
    // pipe controls
    .pipeline_flush_i     (pipeline_flush_i), // FP64_DIV
    .s1o_div_ready_i      (s1o_div_ready), // FP64_DIV
    .div_busy_o           (div_busy), // FP64_DIV
    .div_taking_op_o      (div_taking_op), // FP64_DIV
    .div_rdy_o            (div_rdy_o), // FP64_DIV
    .rnd_taking_div_i     (rnd_taking_div_i), // FP64_DIV
    // operands
    .s1o_signc_i          (s1o_signc), // FP64_DIV
    .s2t_exp13c_i         (s2t_exp13c), // FP64_DIV
    .s2t_shrx_i           (s2t_shrx), // FP64_DIV
    .s1o_fract53a_i       (s1o_fract53a), // FP64_DIV
    .s1o_fract53b_i       (s1o_fract53b), // FP64_DIV
    .s1o_opc_0_i          (s1o_opc_0), // FP64_DIV
    .s1o_dbz_i            (s1o_dbz), // FP64_DIV
    .s1o_op_fp64_arith_i  (s1o_op_fp64_arith), // FP64_DIV
    // DIV outputs
    .div_sign_o           (div_sign_o), // FP64_DIV
    .div_shr_o            (div_shr_o), // FP64_DIV
    .div_shl_o            (div_shl_o), // FP64_DIV
    .div_exp13sh0_o       (div_exp13sh0_o), // FP64_DIV
    .div_fract57_o        (div_fract57_o), // FP64_DIV
    .div_dbz_o            (div_dbz_o) // FP64_DIV
  );

endmodule // pfpu_marocchino_muldiv
